#!/bin/sh
# - raid_level
# - raid_chunk

: "${raid_level:=JBOD}"
: "${raid_chunk:=256}"
: "${mdadm_mode:=create}"

[ -n "$LKP_LOCAL_RUN" ] && exit
. $LKP_SRC/lib/env.sh
is_docker && exit

. $LKP_SRC/lib/fs_ext.sh

for i in 0 1 2 3 4 5; do
	if [ -e /proc/mdstat ]; then
		# $ grep '^md.* : \(in\)\?active' /proc/mdstat | cut -f1 -d:
		# md127
		active_dev=$(grep '^md.* : \(in\)\?active' /proc/mdstat | cut -f1 -d:)
		[ "$active_dev" ] && {
			echo "Current active md dev is: $active_dev"
			log_cmd mdadm -q --stop /dev/$active_dev
		}
	else
		log_cmd modprobe md
	fi
done

check_raid_level()
{
	[ "${raid_level#*raid}" != "$raid_level" ] || exit 0
	[ "${raid_level#*braid}" != "$raid_level" ] && {
		# Need to create env.yaml when matching braid so that export
		# raid_level to is_btrfs_raid_levels() in setup/fs
		cat >> $TMP/env.yaml <<EOF

# setup/md
# used in setup/fs
raid_level: $raid_level
EOF
		exit 0
	}
}
check_raid_level

check_partition_size() {
	# though we can set 'show_part=1' for brd to make those ram disk to
	# show up at /proc/partitions, it's new parameter added lately, hence
	# we still meet troubles with old kernele. Here workaround it.
	[ "${disk_description#*brd}" != "$disk_description" ] && return
	for dev do
		[ "${dev#*:/}" != "$dev" ] && continue

		local part="$(basename $dev)"
		local size="$(grep -w $part /proc/partitions | awk '{ print $3 }')"
		[ -n "$size" ] || {
			echo "failed to get partition size for $dev" >&2
			exit 1
		}
		if [ -n "$prev_size" ]; then
			[ "$size" != "$prev_size" ] || {
				echo "non-equal partition size: $dev $size" >&2
				cat /proc/partitions >&2
				exit 1
			}
		else
			local prev_size=size
		fi
	done
}
check_partition_size $partitions

make_md() {
	# With RAID0 since kernel commit c84a137, we cannot create a new multi-zone array for
	# the disks that are not all same size if we don't specify what layout to use.  So
	# specify layout by inserting raid0 module with default_layout parameter.
	# PS:
	# 1) we can succeed in inserting raid0 module even if default_layout parameter is not supported.
	# 2) We cannot reproduce the issue when creating a new RAID0 for the disks that are all same size.
	if [ "$raid_level" = "raid0" ]; then
		lsmod | grep -q raid0 && modprobe -r raid0
		modprobe raid0 default_layout=1
	fi

	for i in 0 1 2 3 4 5; do
		destroy_devices

		raid_device=/dev/md$i
		[ -b $raid_device ] && continue

		echo y | log_cmd mdadm -q				\
					--$mdadm_mode $raid_device	\
					--chunk=$raid_chunk		\
					--level=$raid_level		\
					--raid-devices=$nr_partitions	\
					--force				\
					--assume-clean $partitions	\
					2> $TMP/mdadm_stderr && return

		sleep 5
	done

	echo "Failed to create RAID!" 1>&2
	cat $TMP/mdadm_stderr 1>&2
	echo \
	cat /proc/mdstat
	cat /proc/mdstat
	exit 1
}

make_md

cat >> $TMP/env.yaml <<EOF

# setup/md
nr_partitions: 1
partitions: $raid_device
# used in setup/fs
raid_device: $raid_device
raid_level: $raid_level
raid_chunk: $raid_chunk
EOF
